package cn.good.yan.service.impl;

import cn.good.yan.config.util.JwtTokenUtil;
import cn.good.yan.entity.Re;
import cn.good.yan.entity.User;
import cn.good.yan.entity.UserLogin;
import cn.good.yan.mapper.UserMapper;
import cn.good.yan.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * User 实体 Service层
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {


    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 登录之后返回 token
     * <p>
     * // 根据用户名查询用户，存在，查询该用户的权限
     * // 单点登录，记录登录信息，保存登录记录
     * // 根据用户、密码 生成token，返回
     *
     * @param username 用户名
     * @param password 密码
     * @param code     验证码
     * @param request  请求
     * @return {@link Re }
     */
    @Override
    public Re login(String username, String password, String code, HttpServletRequest request) {

        // 当前登录的用户
        UserLogin userLogin = new UserLogin();
        userLogin.setUsername(username);
        userLogin.setPassword(password);

        // 先判断验证码 - 是否
        String captcha = (String) request.getSession().getAttribute("captcha");
        if (StringUtils.isEmpty(captcha) || !captcha.equalsIgnoreCase(code)) {
            return Re.error("验证码错误");
        }


        // 登录的逻辑，得到该用户信息
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        // matches 比较2个密码是否一致
        if (null == userDetails || !passwordEncoder.matches(password, userDetails.getPassword())) {
            return Re.error("用户名或者密码错误");
        }

        // 更新security里的用户信息,
        // 参数：userDetails 、凭证（密码）、权限列表
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                userDetails,
                null,
                userDetails.getAuthorities()
        );
        SecurityContextHolder.getContext().setAuthentication(authToken);


        // 生成token
        JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();
        String token = jwtTokenUtil.generateToken(userLogin);
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHeader);
        tokenMap.put("auth", "权限列表xxxx");

        // 生成成功，可以将该用户信息，存到Redis中，后续其他服务，在获取
        // ...

        return Re.success("登录成功", tokenMap);

    }


    //  根据用户名获取用户  -- 可以根据用户名，把用户信息存入Redis中
    @Override
    public User getAdminByUserName(String nickname) {
        LambdaQueryWrapper<User> eq = new LambdaQueryWrapper<User>()
                .eq(User::getUsername, nickname)
                .eq(User::getEnabled, true);
        return userMapper.selectOne(eq);
    }


    // 创建用户
    @Transactional
    @Override
    public User add(String name) {
        User admin = new User();
        // 生成密碼 (根据用户名生成密码，保持一致，方便登录)
        String password = passwordEncoder.encode(name);
        admin.setUsername(name);
        admin.setPassword(password);
        admin.setEnabled(true);  // 启用状态
        userMapper.insert(admin);
        return admin;
    }


    public static void main(String[] args) {
//        // 获取通过用户id
//        Admin user = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        Integer id = user.getId();
    }

}




